﻿using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ImbaTracker.Models;
using ImbaTracker.Content;

namespace ImbaTracker.Controllers {
    [Authorize]
    public class ProjectController : Controller {
        ImbaDBEntities db = new ImbaDBEntities();

        //
        // GET: /Project/

        public ActionResult Index(bool onlyMy = false) {
            var projects = Helper.projectsToView(User, onlyMy);
            return View(projects);
        }

        public ActionResult MyIndex() {
            return RedirectToAction("Index", new { onlyMy = true });
        }

        //
        // GET: /Project/Create/
        [Authorize(Roles = "Administrator")]
        public ActionResult Create() {
            return View();
        }

        [HttpPost]
        public ActionResult Create(Project newProject) {

            if (ModelState.IsValid) {
                db.AddToProjects(newProject);
                db.SaveChanges();

                return RedirectToAction("Index");
            } else {
                return View(newProject);
            }
        }

        // GET: /Project/Members/

        public ActionResult Members(Project p) {
            var proj = (from pr in db.Projects where pr.Id == p.Id select pr).FirstOrDefault();
            if (proj != null) {
                ViewData["Project"] = p.Id;
                //return View(Helper.getMembers(p.Id).ToList());
                return View(proj.Members.ToList());
            } else {
                return RedirectToAction("Index");
            }
        }

        // GET: /Project/Details/

        public ActionResult Details(Project p) {
            ViewData["Project"] = p.Id;
            return View(p);
        }

        public ActionResult Issues(Project project) {
            return RedirectToAction("Index", "Issue", project);
        }

        public ActionResult ClosedIssues(Project project) {
            return RedirectToAction("Index", "Issue", new { onlyMy = false, project = project, closed = true });
        }

        //[AcceptVerbs(HttpVerbs.Delete)]
        public ActionResult Delete(Project proj) {
            var project = db.Projects.First(i => i.Id == proj.Id);
            // We took so much pleasure during writing this code!
            project.Members.Clear();
            project.Owners.Clear();
            while (db.Issues.Count() > 0) {
                var issue = db.Issues.First();
                issue.Predecessor.Clear();
                issue.Successor.Clear();
                issue.Parent = null;
                issue.Children.Clear();
                db.Issues.DeleteObject(issue);
                // Please, don't touch.
                db.SaveChanges();
            }
            project.Issues.Clear();
            //db.Issues.ApplyCurrentValues(proj);
            db.Projects.DeleteObject(project);
            db.SaveChanges();

            return RedirectToAction("Index");
        }

        // GET: /Project/DeleteMember/

        public ActionResult DeleteMember(int userId, int projId) {
            if (!Helper.canAccess(User, userId) && !Helper.isProjectOwner(userId, projId)) {
                return RedirectToAction("Members", Helper.getProject(projId));
            }
            //int projectId = ViewData.ContainsKey("Project") ? (int)ViewData["Project"] : 0;
            var user = db.Users.FirstOrDefault(i => i.Id == userId);
            var project = db.Projects.FirstOrDefault(i => i.Id == projId);
            try {
                if (user.Login != User.Identity.Name && user.Projects.Contains(project)) {
                    user.Projects.Remove(project);
                    project.Members.Remove(user);
                }
                db.SaveChanges();
                return DeleteOwner(userId, projId);
            }
            catch (Exception e) {
                return RedirectToAction("Members", Helper.getProject(projId));
            }
        }

        public ActionResult DeleteOwner(int userId, int projId) {
            //int projectId = ViewData.ContainsKey("Project") ? (int)ViewData["Project"] : 0;
            if (Helper.getUser(userId).Login == User.Identity.Name ||
                    !User.IsInRole("Administrator") && !Helper.isProjectOwner(Helper.curUserId(User), projId)) {
                return RedirectToAction("Members", Helper.getProject(projId));
            }
            try {
                var user = db.Users.FirstOrDefault(i => i.Id == userId);
                var project = db.Projects.FirstOrDefault(i => i.Id == projId);
                if (user.Login != User.Identity.Name && user.OwnedProjects.Contains(project)) {
                    user.OwnedProjects.Remove(project);
                    project.Owners.Remove(user);
                }
                db.SaveChanges();
                return RedirectToAction("Members", project);
            }
            catch (Exception e) {
                return RedirectToAction("Members", Helper.getProject(projId));
            }
        }

        public ActionResult AddOwner(int userId, int projId) {
            if (!User.IsInRole("Administrator") && !Helper.isProjectOwner(userId, projId)) {
                return RedirectToAction("Members", Helper.getProject(projId));
            }
            try {
                var user = db.Users.FirstOrDefault(i => i.Id == userId);
                var project = db.Projects.FirstOrDefault(i => i.Id == projId);
                if (!user.OwnedProjects.Contains(project)) {
                    user.OwnedProjects.Add(project);
                    project.Owners.Add(user);
                }
                if (!user.Projects.Contains(project)) {
                    user.Projects.Add(project);
                    project.Members.Add(user);
                }
                db.SaveChanges();
                return RedirectToAction("Members", project);
            }
            catch (Exception e) {
                return RedirectToAction("Members", Helper.getProject(projId));
            }
        }

        public ActionResult AddMember(int projId) {
            if (!User.IsInRole("Administrator") && !Helper.isProjectOwner(Helper.curUserId(User), projId)) {
                return RedirectToAction("Members", Helper.getProject(projId));
            }
            var pr = db.Projects.Where(p => p.Id == projId).ToList();
            ViewData["Project"] = new SelectList(pr, "Id", "Name");
            var users = db.Users.ToList();

            var newUsers = new List<User>();
            foreach (var member in users) {
                if (!Helper.isProjectMember(member.Id, projId)) {
                    newUsers.Add
                        (new User() {
                            Id = member.Id,
                            Login = member.Id + ". " + member.Login
                        });
                }
            }

            ViewData["Users"] = new SelectList(newUsers, "Id", "Login");
            var model = new AddMemberModel();
            model.Project = projId;
            return View(model);
        }

        [HttpPost]
        public ActionResult AddMember(AddMemberModel model) {
            var project = db.Projects.FirstOrDefault(p => p.Id == model.Project);
            var user = db.Users.FirstOrDefault(u => u.Id == model.Id);
            if (ModelState.IsValid) {
                project.Members.Add(user);
                user.Projects.Add(project);
                db.SaveChanges();
            }
            return RedirectToAction("Members", project);
        }

        public ActionResult Edit(int id = 0) {
            try {
                if (Helper.isProjectOwner(Helper.curUserId(User), id) || User.IsInRole("Administrator")) {
                    Project project = db.Projects.Single(p => p.Id == id);
                    return View(project);
                } else {
                    return RedirectToAction("Index");
                }
            }
            catch (Exception e) {
                return RedirectToAction("Error");
            }

        }

        //
        // POST: /Project/Edit/

        [HttpPost]
        public ActionResult Edit(Project project) {
            if (ModelState.IsValid) {
                // FUCK DAT SHIT, I'm going home, guys
                try {
                    Project target = db.Projects.Single(p => p.Id == project.Id);
                    target.Name = project.Name;
                    db.Projects.ApplyCurrentValues(target);
                    db.SaveChanges();
                    return RedirectToAction("Index");
                }
                catch (Exception e) {
                    return RedirectToAction("Error");
                }
            }

            return View(project);
        }

        public ActionResult AddIssue(Project project) {
            return RedirectToAction("Create", "Issue", project);
        }

    }
}
